﻿namespace Iesi.Collections.Generic
{
    using Iesi.Collections;
    using System;
    using System.Collections;
    using System.Collections.Generic;

    [Serializable]
    public sealed class SynchronizedSet<T> : Set<T>
    {
        private ISet<T> mBasisSet;
        private object mSyncRoot;

        public SynchronizedSet(ISet<T> basisSet)
        {
            this.mBasisSet = basisSet;
            this.mSyncRoot = ((ICollection) basisSet).SyncRoot;
            if (this.mSyncRoot == null)
            {
                throw new NullReferenceException("The Set you specified returned a null SyncRoot.");
            }
        }

        public sealed override bool Add(T o)
        {
            lock (this.mSyncRoot)
            {
                return this.mBasisSet.Add(o);
            }
        }

        public sealed override bool AddAll(ICollection<T> c)
        {
            Set<T> set;
            lock (((ICollection) c).SyncRoot)
            {
                set = new HashedSet<T>(c);
            }
            lock (this.mSyncRoot)
            {
                return this.mBasisSet.AddAll(set);
            }
        }

        public sealed override void Clear()
        {
            lock (this.mSyncRoot)
            {
                this.mBasisSet.Clear();
            }
        }

        public override object Clone()
        {
            return new SynchronizedSet((ISet) this.mBasisSet.Clone());
        }

        public sealed override bool Contains(T o)
        {
            lock (this.mSyncRoot)
            {
                return this.mBasisSet.Contains(o);
            }
        }

        public sealed override bool ContainsAll(ICollection<T> c)
        {
            Set<T> set;
            lock (((ICollection) c).SyncRoot)
            {
                set = new HashedSet<T>(c);
            }
            lock (this.mSyncRoot)
            {
                return this.mBasisSet.ContainsAll(set);
            }
        }

        public sealed override void CopyTo(T[] array, int index)
        {
            lock (this.mSyncRoot)
            {
                this.mBasisSet.CopyTo(array, index);
            }
        }

        public sealed override IEnumerator<T> GetEnumerator()
        {
            return this.mBasisSet.GetEnumerator();
        }

        protected override void NonGenericCopyTo(Array array, int index)
        {
            lock (this.mSyncRoot)
            {
                ((ICollection) this.mBasisSet).CopyTo(array, index);
            }
        }

        public sealed override bool Remove(T o)
        {
            lock (this.mSyncRoot)
            {
                return this.mBasisSet.Remove(o);
            }
        }

        public sealed override bool RemoveAll(ICollection<T> c)
        {
            Set<T> set;
            lock (((ICollection) c).SyncRoot)
            {
                set = new HashedSet<T>(c);
            }
            lock (this.mSyncRoot)
            {
                return this.mBasisSet.RemoveAll(set);
            }
        }

        public sealed override bool RetainAll(ICollection<T> c)
        {
            Set<T> set;
            lock (((ICollection) c).SyncRoot)
            {
                set = new HashedSet<T>(c);
            }
            lock (this.mSyncRoot)
            {
                return this.mBasisSet.RetainAll(set);
            }
        }

        public sealed override int Count
        {
            get
            {
                lock (this.mSyncRoot)
                {
                    return this.mBasisSet.Count;
                }
            }
        }

        public sealed override bool IsEmpty
        {
            get
            {
                lock (this.mSyncRoot)
                {
                    return this.mBasisSet.IsEmpty;
                }
            }
        }

        public override bool IsReadOnly
        {
            get
            {
                lock (this.mSyncRoot)
                {
                    return this.mBasisSet.IsReadOnly;
                }
            }
        }

        public sealed override bool IsSynchronized
        {
            get
            {
                return true;
            }
        }

        public sealed override object SyncRoot
        {
            get
            {
                return this.mSyncRoot;
            }
        }
    }
}

